﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Web;
using OperationPlugins.Validators;

namespace OperationPlugins.Applications.Remoting
{
    [Serializable]
    public abstract class SandboxRunner : MarshalByRefObject, ISandboxRunner
    {
        /// <summary>
        /// The sandbox context.
        /// </summary>
        protected virtual SandboxContext Context { set; get; }

        object ISandboxRunner.Invoke(SandboxContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            Context = context;
            return GetType().InvokeMember("Run", BindingFlags.InvokeMethod, null, this, new object[] { });
        }

        /// <summary>
        /// Initializes the environment.
        /// </summary>
        protected virtual void Initialize()
        {
            OperationPluginsContext.SwitchContext(Context.OperationPluginsContext);

            if (OperationPluginsEnvironment.IsInitialized == false)
            {
                OperationPluginsEnvironment.InitializeByUsingAssemblies(GetCompositionAssemblies());
            }

        }

        private Assembly[] GetCompositionAssemblies()
        {
            List<Assembly> l = new List<Assembly>();
            return l.ToArray();
        }
      
        protected virtual SandboxRunnerReturnValue Execute()
        {
            Runner runner;

            ApplicationServiceTypes serviceType;
            if (Context.ApplicationRequestContext.TryGetServiceType(out serviceType) == false)
            {
                throw new InvalidOperationException("Could not resolve the service type.");
            }

            switch (serviceType)
            {
                case ApplicationServiceTypes.Validator:
                    runner = new ValidatorRunner();
                    break;
                case ApplicationServiceTypes.Handler:
                    runner = new HandlerRunner();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return runner.Run(this);            
        }

        private abstract class Runner
        {
            protected SandboxRunnerReturnValue ReturnValue { get; private set; }

            protected Runner()
            {
                ReturnValue = new SandboxRunnerReturnValue();
            }

            public abstract SandboxRunnerReturnValue Run(SandboxRunner sandboxRunner);
        }

        private sealed class ValidatorRunner : Runner
        {
            public override SandboxRunnerReturnValue Run(SandboxRunner sandboxRunner)
            {



                ReturnValue.Messages = OperationPluginsContext.Current.Messages;
                return ReturnValue;
            }
        }

        private sealed class HandlerRunner : Runner
        {
            public override SandboxRunnerReturnValue Run(SandboxRunner sandboxRunner)
            {
                return null;
            }
        }

    }
}